#-*- coding:utf-8 -*-
#!/usr/bin/env python
import select, os
import socket
import queue

import Reply

server_address = ('', 18091)
parse_address = ('', 9001)
store_address = ('localhost', 9002)

"""
try:
	parse_sockfd = socket.socket()
except Exception as err:
	print(err)
try:
	parse_sockfd.connect(parse_address)
except Exception as err:
	print(err)
"""

try:
	store_sockfd = socket.socket()
except Exception as err:
	print(err)

try:
	store_sockfd.connect(store_address)
except Exception as err:
	print(err)

#create a socket
server = socket.socket(socket.AF_INET,socket.SOCK_STREAM)

#set non-blocking
server.setblocking(False)

#set option reused
server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR  , 1)

server.bind(server_address)

server.listen(20)

#sockets from which we except to read
inputs = [server]

#sockets from which we expect to write
outputs = []

#Outgoing message queues (socket:Queue)
message_queues = {}

#A optional parameter for select is TIMEOUT
timeout = 60

reply = Reply.replyData()

while inputs:
	#print("waiting for next event")
	readable , writable , exceptional = select.select(inputs, outputs, inputs, timeout)
	#readable , writable , exceptional = select.select(inputs, outputs, inputs, timeout)

	# When timeout reached , select return three empty
	# lists
	if not (readable or writable or exceptional) :
		print("Time out ! ")
		continue    

	for cur_sock in readable :
		if cur_sock is server:
			# A "readable" socket is ready to accept a connection
			connection, client_address = cur_sock.accept()
			print("    connection from ", client_address)
			connection.setblocking(0)
			inputs.append(connection)
			message_queues[connection] = queue.Queue()
		else:
			try:
				data = cur_sock.recv(1024)
			except Exception as err:
				print(err, "closing", client_address)
				if cur_sock in outputs:
					outputs.remove(cur_sock)
				inputs.remove(cur_sock)
				cur_sock.close()
				del message_queues[cur_sock]
				continue
			if data :
				#print(" received " , data , "from ", cur_sock.getpeername())
				datas = reply.reply(data, message_queues)
				print(data)
				try:
					store_sockfd.sendall(data)
				except Exception as err:
					print(err)
				#store_sockfd.send(data)
				for atom in datas:
					#print("reply--->>", atom)
					message_queues[cur_sock].put(atom)
				# Add output channel for response
				if cur_sock not in outputs:
					outputs.append(cur_sock)
			else:
				#Interpret empty result as closed connection
				print("  closing", client_address)
				if cur_sock in outputs :
					outputs.remove(cur_sock)
				inputs.remove(cur_sock)
				cur_sock.close()
				#remove message queue 
				del message_queues[cur_sock]
	for cur_sock in writable:
		try:
			next_msg = message_queues[cur_sock].get_nowait()
		except queue.Empty:
			#print(" ", cur_sock.getpeername(), "queue empty")
			outputs.remove(cur_sock)
		except Exception as err:
			print(err)
		else:
			print(" sending " , next_msg , " to ", cur_sock.getpeername())
			cur_sock.send(next_msg)
			store_sockfd.sendall(next_msg)

	for cur_sock in exceptional:
		print(" exception condition on ", cur_sock.getpeername())
		#stop listening for input on the connection
		inputs.remove(cur_sock)
		if cur_sock in outputs:
			outputs.remove(cur_sock)
		cur_sock.close()
		#Remove message queue
		del message_queues[cur_sock]


